127.0.0.1にLet' Encryptで証明書を発行してhttpsでのローカル開発と本番の差異を低減するための具体的な手順
やりたいこと
https://localhostしたくなるので、127.0.0.1に対して本物のLet' Encryptの証明書を発行してローカルでの開発と本番環境の差異を低減したい。
https://gyazo.com/985b862068c71b21fe339f271f12ed33
背景
手順
ドメインや証明書の発行も含めて無料で行う。サーバーも不要。
ドメインを取得する
ドメインを取得するは「Freenom」と検索するとたくさん出てくる。以下は画像付きで親切そうだった。
証明書を取得する
まずローカル環境を汚したくないのでDockerコンテナ内で作業する。(Dockerは必須ではない)
以下のようにしてコンテナ内に入る。
code:bash
docker run -it -v $PWD/shared:/shared ubuntu:18.04
($PWD/shared:/sharedをつけるのは、後でコンテナ内の証明書をホスト環境に持ってくるため。-v $PWD/letsencrypt:/etc/letsencrypt/でも良いかもしれない。)
以下のコマンドを実行して必要なツールをインストールする。
code:bash
apt update \
&& apt-get install -y software-properties-common \
&& add-apt-repository -y universe \
&& add-apt-repository -y ppa:certbot/certbot \
&& apt-get update \
&& apt-get install -y python-certbot-apache
上記のコマンドの途中で「Geographic area」と「Time zone」を尋ねられるかもしれない。そのときは「Geographic area」は「6」(Asia)で「Time zone」は「79」(Tokyo)を入力した。
以下のコマンドで証明書の発行を開始する。
(localhost0.mlというのを取得したので-d localhost0.mlを指定した。)
code:bash
certbot --manual --preferred-challenges dns certonly -d 自分のドメイン
上記のコマンドをたたいてメールアドレスが求められたら入力する。
上記のコマンドを実行すると途中で以下のようなメッセージが出る。
Please deploy a DNS TXT record under the name
_acme-challenge.localhost0.ml with the following value:
画像だと以下のよう。ここでDNSの管理画面でメッセージにある内容でDNSのTXTを追加する。まだEnterするのは待つ。
https://gyazo.com/79861cd28c7f2a81690cfd95630c0587
https://gyazo.com/2caef23fad0ba25677f0f98f71d10dd7
DNSが浸透するのに時間がかかるのでdig -t TXT localhost0.mlなどして確認すると良いかもしれない(結局確認できなかったのだが...)。
おそらく浸透する前にEnterしてしまったのか、失敗すると以下のように出力される。
Failed authorization procedure. localhost0.ml (dns-01): urn:ietf:params:acme:error:dns :: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.localhost0.ml - check that a DNS record exists for this domain
IMPORTANT NOTES:
- The following errors were reported by the server:
Domain: localhost0.ml
Type: None
Detail: DNS problem: NXDOMAIN looking up TXT for
_acme-challenge.localhost0.ml - check that a DNS record exists for
this domain
- Your account credentials have been saved in your Certbot
configuration directory at /etc/letsencrypt. You should make a
secure backup of this folder now. This configuration directory will
also contain certificates and private keys obtained by Certbot so
making regular backups of this folder is ideal.
_acme-challengeの値はcertbotを実行するたびに変わる。なるべく長めに待つの良いと思う。
Enterして成功した場合は以下のように表示される。これで証明書などの取得ができた。
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/localhost0.ml/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/localhost0.ml/privkey.pem
Your cert will expire on 2020-11-08. To obtain a new or tweaked
version of this certificate in the future, simply run certbot
again. To non-interactively renew *all* of your certificates, run
"certbot renew"
- If you like Certbot, please consider supporting our work by:
/etc/letsencrypt/live/自分のドメイン/の中にあるfullchain.pemとprivkey.pemがあればHTTPSのサーバーが立てられる。このページのDockerコンテナを使った方法なら/sharedにその2つのファイルをコピーすればホスト環境に持ってこれる。(cp -a /etc/letsencrypt/ /shared/)
実際にHTTPSのサーバーを立てる
以下のコードはfullchain.pemとprivkey.pemが今いるディレクトリにあることを前提としている(必要に応じてserverKeyPathとserverCrtPathを変更すれば良い)。
code:index.js
const https = require("https");
const fs = require("fs");
const serverKeyPath = "./privkey.pem";
const serverCrtPath = "./fullchain.pem";
const httpsPort = 8443;
https.createServer({
key: fs.readFileSync(serverKeyPath),
cert: fs.readFileSync(serverCrtPath),
}, (req, res) => res.end("hello, world")
).listen(httpsPort, () => {
console.log(Listening HTTPS on ${httpsPort}...);
});
上記のファイルをindex.jsとして保存したら以下のコマンドでHTTPSサーバーが立てられる。
code:bash
node index.js
以下のようにChrome、Firefox、Safariで にアクセスすることができた。 Google Chrome
https://gyazo.com/1234735f0d3923593bc916925f5ad8b6
Firefox
https://gyazo.com/6592fda54adcf3d90712914f3049b581
Safari
https://gyazo.com/aa281ba8871193a8e151f5b03b4d3ba0
最後に: Let's Encryptなど
たとえ127.0.0.1に対してでもprivkey.pemの保管は慎重に行うべきだと思う。粗末に扱って漏洩が多発すればLet's Encrypt自体の信用の低下もするかもしれない。そのため慎重に管理すべきだと思う。 「For local development」のセクションには最良の選択として「自己署名証明書」を利用することを勧めていた。
The best option: Generate your own certificate, either self-signed or signed by a local root, and trust it in your operating system’s trust store. Then use that certificate in your local web server. See below for details.
mkcertというツールが便利で多くの人が利用していると思う。 だが@jxckさんと同意見ではあるが、OSSで開発されていて透明性はあるがこういった"強いツール"を信用してローカルのマシンが危険な状態になる可能性を作りたくない気持ちがある。